/*
 * Copyright (C) 2010-2011 sunjumper@163.com
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *  http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package mf.mfrpc.client;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import mf.mfrpc.InvokeException;
import mf.mfrpc.serialize.Parser;
import mf.mfrpc.util.LocationUtil;

/**
 * Http方式的WebServices请求端。
 */
public class WSHttpClient extends RPCHttpClient {

    /** interface proxy cache */
    private static final Map<Class, Object> ProxyCache = new HashMap<Class, Object>();

    /** method url cache */
    private static final Map<Method, String> MethodCache = new HashMap<Method, String>();

    /** webservices url */
    private String path;

    public WSHttpClient(String url, Parser parser) {
        super(url, parser);
        this.path = url;
    }

    public WSHttpClient(Parser parser) {
        super(parser);
    }
    /** interface proxy */
    private final InvocationHandler PRCHandler = new InvocationHandler() {

        @Override
        public Object invoke(Object proxy, Method method, Object... args) throws InvokeException {

            //get url from cache
            url = MethodCache.get(method);
            if (url == null) {
                //set the true url
                url = LocationUtil.locate(path, method);
                MethodCache.put(method, url);
                //System.out.println(path + "," + url);
            }
            return WSHttpClient.super.invoke(args);
        }
    };

    /** 创建接口代理 */
    private static <T> T create(Class<T> inter, InvocationHandler handler) {
        try {
            return (T) Proxy.getProxyClass(inter.getClassLoader(), inter).getConstructor(InvocationHandler.class).newInstance(handler);
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * 创建接口WebServices代理类。
     *
     * @param clazz 接口类型。
     * 
     * @return WebServices代理类。
     */
    public <T> T create(Class<T> clazz) {
        T proxy = (T) ProxyCache.get(clazz);
        if (proxy != null) {
            return proxy;
        }
        proxy = create(clazz, PRCHandler);
        ProxyCache.put(clazz, proxy);
        return proxy;
    }

    /**
     * 清除方法缓存。
     */
    public void clearCache() {
        MethodCache.clear();
        ProxyCache.clear();
    }
}
